####################################################################################
########                       BlackBirdDaemon                               #######
########                       Scopel Emanuele                               #######
########                      escopel@alice.it                               #######
########                         license GPL3                                #######
####################################################################################



from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor
from twisted.python import log
import time, sys, os
import pexpect
import ConfigParser



CFG_FILE = '/home/emanuele/Progetti/BoaProgetti/BlackBirdDaemon/config.cfg'


class BlackBirdDaemon_Finder(DatagramProtocol):

    def __init__(self):
    	log.startLogging(sys.stdout)
    	self.Timeout = 100
    	config = ConfigParser.ConfigParser()
    	#open configuration file
    	fd = open(os.path.expanduser(CFG_FILE))
    	config.readfp(fd)
    	#read server parameter
    	self.host = config.get('Client', 'ip')
    	self.port = config.getint('Client', 'port')
    	self.name = config.get('Client', 'name')	
    	#close configuration file
    	fd.close()
    	
    def startProtocol(self):
        self.transport.connect(self.host, self.port)
        self.datagramTrasmit() 
    
    def datagramTrasmit(self):
    	log.msg('Searching server...')
    	self.transport.write('hello')

    	    
    def datagramReceived(self, data, (host, port)):
        if data == 'hello client':
        	self.transport.write('%s' %self.name)
        		
        elif data == 'OK':
        	log.msg('Run Backup...')
        	executor = BlackBirdDaemon_Executor()
        	status = executor.RunBackUp()
        	if status == True:
        		log.msg('Backup completate succerfull!!!')
        		self.transport.write('%s backup completed, disconnection...' %self.name)
        		log.msg('Shut down...')
        		reactor.stop()
        	else:
        		log.msg('Backup completate unsuccerfull!!!')
        		self.transport.write('%s backup uncompleted, disconnection...' %self.name)
        		log.msg('Shut down...')
        		reactor.stop()  

    def connectionRefused(self):
        log.msg('Server not found...')
        if self.Timeout > 0:
        	reactor.callLater(5, self.datagramTrasmit)
        	self.Timeout = self.Timeout -1
        else:
        	log.msg('Timeout no route to host...')
        	reactor.stop()
        
################################################################################

class BlackBirdDaemon_Executor():

    def __init__(self):
    	config = ConfigParser.ConfigParser()
    	#open configuration file
    	fd = open(os.path.expanduser(CFG_FILE))
    	config.readfp(fd)
    	
    	#read server parameter
    	self.host = config.get('Client', 'ip')
    	self.user = config.get('Client', 'user')
    	self.passwd = config.get('Client', 'password')
    	
    	#read rsync parameter
    	self.rsync = config.get('Daemon', 'rsync')
        self.GeneralOption = config.get('Daemon', 'option')
    	
    	#read dir source
    	self.dir_source = {}
    	self.dir_dest = {}
    	self.opzioni = {}
    	self.sospesi = {}
    	self.fileEsclusi = {}
    	
        for key in config.items('Local'):
            self.dir_source[key[0]] = key[1]
        for key in config.items('Remote'):
            self.dir_dest[key[0]] = key[1]
        for key in config.items('Opzioni'):
            self.opzioni[key[0]] = key[1]
        for key in config.items('Sospesi'):
            self.sospesi[key[0]] = key[1]
        for key in config.items('FileEsclusi'):
            self.fileEsclusi[key[0]] = key[1]
    	#close configuration file
    	fd.close()
	
    def RunBackUp(self):
    	for key in self.dir_source.keys():
    	    opt = '-' + self.opzioni[key] + ' ' + self.GeneralOption
    	    if self.sospesi[key] == 'False':
    	        log.msg('Avvio copia %s' %key)
                status = self.__StartProcess(self.dir_source[key], self.dir_dest[key], opt)
                if status == None :
                    log.msg('Errore durante la copia di %s' %key)
            else:
                log.msg("Copia di %s e' sospesa!" %key)
    	return True
	
    def __StartProcess(self,local_path, remot_path, option):
    	status = self.__rsync_command(self.rsync, self.user, self.host, local_path, remot_path, option, self.passwd)
    	return status
	
	
    def __rsync_command (self, rsync, user, host, local_path, remot_path, option, password):
    	ssh_newkey = 'Are you sure you want to continue connecting'
    	#rsync -auvrd --progress /home/emanuele/Progetti/PicProgetti/bootloader/
	#emanuele@192.168.1.76:/home/emanuele/Progetti/PicProgetti/bootloader/
        cmd = '%s %s %s %s@%s:%s'%(rsync, option, local_path, user, host, remot_path)
        log.msg('eseguo %s ' %cmd)
    	child = pexpect.spawn(cmd)
    	i = child.expect([pexpect.TIMEOUT, ssh_newkey, 'password: '])
    	if i == 0: # Timeout
    	    	log.msg('ERROR!')
    	    	log.msg('SSH could not login. Here is what SSH said:')
    	    	log.msg('%s %s' %(child.before, child.after))
    	    	return None
    	if i == 1: # SSH does not have the public key. Just accept it.
    	    	child.sendline ('yes')
    	    	child.expect ('password: ')
    	    	i = child.expect([pexpect.TIMEOUT, 'password: '])
    		if i == 0: # Timeout
        	    	log.msg('ERROR!')
        	    	log.msg('SSH could not login. Here is what SSH said:')
        	    	log.msg('%s %s' %(child.before, child.after))
        	    	return None       
    	if i == 2:
	    	child.sendline(password)
	    	child.expect(pexpect.EOF)
	    	return True  
    
    
################################################################################

    
reactor.listenUDP(0, BlackBirdDaemon_Finder())
reactor.run()	

